﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Tanks;
using Microsoft.Xna.Framework.Graphics;

namespace PositionUtils
{
    static class mPositionUtils
    {

        public static double computeDistance(Vector2 one, Vector2 two)
        {
            return Math.Sqrt(Math.Pow((one.X-two.X),2) + Math.Pow((one.Y-two.Y),2));
        }

        public  static Vector2[] computeBoards(Vector2 position, float rotation, float height, float width)
        {
            Vector2[] boards = new Vector2[4];
            float cos = (float)Math.Cos(rotation);
            float sin = (float)Math.Sin(rotation);
            boards[0] = new Vector2((float)((width / 2) * cos - (height / 2) * sin) + position.X,
                                    (float)((width / 2) * sin + (height / 2) * cos) + position.Y);
            boards[1] = new Vector2((float)((-width / 2) * cos - (height / 2) * sin) + position.X,
                                    (float)((-width / 2) * sin + (height / 2) * cos) + position.Y);
            boards[2] = new Vector2((float)((width / 2) * cos - (-height / 2) * sin) + position.X,
                                    (float)((width / 2) * sin + (-height / 2) * cos) + position.Y);
            boards[3] = new Vector2((float)((-width / 2) * cos - (-height / 2) * sin) + position.X,
                                    (float)((-width / 2) * sin + (-height / 2) * cos) + position.Y);
            return boards;
        }

        //проверка на коллизии
        //true - колизия есть
        //fase - колизии нету
        public  static bool checkCollisions(IFieldObject one, IFieldObject two)
        {
            Vector2[] bOne = one.getBoards();
            Vector2[] bTwo = two.getActualBoards();
            
            //если не найдина коллизия в квадрате
            if (!checkQuard(bOne, bTwo))
            {
                return false;
            }
            //иначе, дальнейшая проверка на коллизии
            //первый перпендикулярен системе координаты
            //если не найдина коллизия в квадрате

            Vector2[] oRot = rotationCordSystem(bOne, -one.getActualRotation());
            Vector2[] tRot = rotationCordSystem(bTwo, -one.getActualRotation());
            if (!checkQuard(oRot, tRot))
            {
                return false;
            }
            //иначе, дальнейшая проверка на коллизии
            //второй перепендикулярен системе координат
            oRot = rotationCordSystem(bOne, -two.getActualRotation());
            tRot = rotationCordSystem(bTwo, -two.getActualRotation());

            if (!checkQuard(oRot, tRot))
            {
                return false;
            }
            one.collisionFounded(two);
            two.collisionFounded(one);
            //if (one.Properties.IsShoot && !two.Properties.IsShoot)
            //    two.collisionNotFounded();
            //if (two.Properties.IsShoot && !one.Properties.IsShoot)
            //    one.collisionNotFounded();
           
            return true;
        }
        //проверка с проекцией на две оси, квадраты
        private static bool      checkQuard(Vector2[] one, Vector2[] two)
        {
            float omin = getMinX(one);
            float omax = getMaxX(one);
            float tmin = getMinX(two);
            float tmax = getMaxX(two);
            //если проекции не совпали, то пересечений нету
            if (!checkProection(omin, omax, tmin, tmax))
            {
                return false;
            }

            omin = getMinY(one);
            omax = getMaxY(one);
            tmin = getMinY(two);
            tmax = getMaxY(two);
            if (!checkProection(omin, omax, tmin, tmax))
            {
                return false;
            }

            return true;
        }
        //проверка проекции на оси
        private static bool      checkProection(float omin, float omax, float tmin, float tmax)
        {
            if (((omin <= tmin) && (omax <= tmin)) ||
                ((omin >= tmax) && (omax >= tmax)))
                return false;
            return true;
        }
        private static float     getMinX(Vector2[] buf)
        {
            int index = 0;
            for (int i = 1; i < buf.Length; i++)
            {
                if (buf[i].X < buf[index].X)
                    index = i;
            }
            return buf[index].X;
        }
        private static float     getMinY(Vector2[] buf)
        {
            int index = 0;
            for (int i = 1; i < buf.Length; i++)
            {
                if (buf[i].Y < buf[index].Y)
                    index = i;
            }
            return buf[index].Y;
        }
        private static float     getMaxX(Vector2[] buf)
        {
            int index = 0;
            for (int i = 1; i < buf.Length; i++)
            {
                if (buf[i].X > buf[index].X)
                    index = i;
            }
            return buf[index].X;
        }
        private static float     getMaxY(Vector2[] buf)
        {
            int index = 0;
            for (int i = 1; i < buf.Length; i++)
            {
                if (buf[i].Y > buf[index].Y)
                    index = i;
            }
            return buf[index].Y;
        }
        //поворот системы координат, на угол alpha
        private static Vector2[] rotationCordSystem(Vector2[] mas, float alpha)
        {
            Vector2[] buf = new Vector2[mas.Length];
            for (int i = 0; i < mas.Length; i++)
            {
                buf[i] = new Vector2( (float)(mas[i].X * Math.Cos(alpha) - mas[i].Y * Math.Sin(alpha)),
                   (float)(mas[i].Y * Math.Cos(alpha) + mas[i].X * Math.Sin(alpha)));
            }
            return buf;
        }
    }
}
